package com.campus_activity.campus_activity.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus_activity.campus_activity.constant.HttpStatus;
import com.campus_activity.campus_activity.domain.po.Activity;
import com.campus_activity.campus_activity.domain.po.UserActivity;
import com.campus_activity.campus_activity.domain.vo.ParticipateStatusVO;
import com.campus_activity.campus_activity.enums.ActivityStatusEnum;
import com.campus_activity.campus_activity.exception.BusinessException;
import com.campus_activity.campus_activity.mapper.ActivityMapper;
import com.campus_activity.campus_activity.service.ActivityService;
import com.campus_activity.campus_activity.service.UserActivityService;
import com.campus_activity.campus_activity.mapper.UserActivityMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * @author 73493
 * @description 针对表【t_user_activity(用户活动记录表)】的数据库操作Service实现
 * @createDate 2023-04-24 17:07:12
 */
@Service
@RequiredArgsConstructor
public class UserActivityServiceImpl extends ServiceImpl<UserActivityMapper, UserActivity>
        implements UserActivityService {

    private final ActivityService activityService;

    private final ActivityMapper activityMapper;

    private final UserActivityMapper userActivityMapper;


    @Override
    public boolean participateActivity(Long id) {
        //获取用户id
//        Long userId = StpUtil.getLoginIdAsLong();
        //TODO 修改用户id
        Long userId = 1L;
        //查询是否在开始时间
        Activity activity = activityMapper.selectById(id);

        if (activity == null) {
            throw new BusinessException(HttpStatus.ERROR, "该活动不存在!");
        }

        //如果活动尚未开始
        LocalDateTime now = LocalDateTime.now();
        if (activity.getBeginTime().isAfter(now)) {
            throw new BusinessException(HttpStatus.ERROR, "活动尚未开始!");
        }

        //如果活动已经结束了
        if (activity.getEndTime().isBefore(now)) {
            throw new BusinessException(HttpStatus.ERROR, "活动已经结束!");
        }

        //判断该活动是否已达人数上限
        if (activity.getHasNumber() == activity.getNeedNumber()) {
            throw new BusinessException(HttpStatus.ERROR, "活动已达人数上限!");
        }

        //互斥锁用于insert仅仅适用单机情况下,如果需要做分布式请用分布式锁
        synchronized (userId.toString().intern()) {
            //防止事务失效用proxy对象进行代理操作
            UserActivityService proxy = (UserActivityService) AopContext.currentProxy();
            return proxy.createActivityOrder(id);
        }
    }

    @Override
    @Transactional
    public boolean createActivityOrder(Long activityId) {

        //获取用户id
//        Long userId = StpUtil.getLoginIdAsLong();
        //TODO 修改用户id
        Long userId = 1L;

//      //查询是否可以参加
        Long count = this.query().eq("user_id", userId).eq("activity_id", activityId)
                .eq("status", ActivityStatusEnum.ATTEND.getStatus()).count();

        if (count > 0) {
            throw new BusinessException(HttpStatus.ERROR, "一个用户只能参加一次!");
        }

        //乐观锁用于update
        boolean success = activityMapper.updateById(activityId);

        //如果不成功则返回
        if (!success) {
            throw new BusinessException(HttpStatus.ERROR, "活动人数已达上限!");
        }

        //TODO 想优化代码写的太抽象了

        //查询活动是否存在
        LambdaQueryWrapper<UserActivity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserActivity::getUserId, userId);
        lambdaQueryWrapper.eq(UserActivity::getActivityId, activityId);
        UserActivity userActivity = this.getOne(lambdaQueryWrapper);

        //如果不存在则插入
        if (userActivity == null) {
            userActivity = new UserActivity();
            userActivity.setStatus(ActivityStatusEnum.ATTEND.getStatus());
            userActivity.setActivityId(activityId);
            userActivity.setUserId(userId);
        }

        userActivity.setStatus(ActivityStatusEnum.ATTEND.getStatus());
        //参加
        success = this.saveOrUpdate(userActivity);
        return success;
    }


    @Override
    public boolean exitActivity(Long id) {

        //查询状态是否已经报名成功
        Long userId = StpUtil.getLoginIdAsLong();
        LambdaQueryWrapper<UserActivity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserActivity::getUserId, userId);
        lambdaQueryWrapper.eq(UserActivity::getActivityId, id);
        //获取记录
        UserActivity userActivity = userActivityMapper.selectOne(lambdaQueryWrapper);

        if (userActivity == null) {
            throw new BusinessException(HttpStatus.ERROR, "您未参加该活动!");
        }

        int status = userActivity.getStatus();

        //如果已经参加
        if (ActivityStatusEnum.ATTEND.getStatus() != status) {
            throw new BusinessException(HttpStatus.ERROR, "您未参加该活动!");
        }

        //退出活动人数- 1 记录状态更改即可

        return false;
    }


    @Override
    public ParticipateStatusVO getParticipateStatus(Long id) {
        //获取用户的id TODO 修改用户id
//        Long userId = StpUtil.getLoginIdAsLong();
        Long userId = 1L;
        LambdaQueryWrapper<UserActivity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserActivity::getUserId, userId);
        lambdaQueryWrapper.eq(UserActivity::getActivityId, id);
        UserActivity userActivity = this.getOne(lambdaQueryWrapper);

        //如果为空则未参加过该活动
        if (userActivity == null) {
            throw new BusinessException(HttpStatus.ERROR, "您未参加过该活动!");
        }

        //返回用户对当前活动状态
        int status = userActivity.getStatus();
        //遍历枚举返回其结果
        for (ActivityStatusEnum activityStatusEnum : ActivityStatusEnum.values()) {
            if (activityStatusEnum.getStatus() == status) {
                return new ParticipateStatusVO(activityStatusEnum.getStatus(), activityStatusEnum.getName());
            }
        }

        throw new BusinessException(HttpStatus.ERROR, "用户参加活动状态异常!");
    }

}




